buildFileList=[
    'setup.py',
    'makefile',
]

from textwrap import fill
from types import ListType

import socket
import time
import hashlib
import os
import sys
import subprocess
import httplib
import builderPie.demjson as json

#-----------------------------------
#
#-----------------------------------
def run(cmd):
    args={
        'shell': True,
        'stderr': subprocess.PIPE,
        'stdout': subprocess.PIPE
    }
    
    pipe=subprocess.Popen(cmd, **args)
    pipe.wait()
    
    result={
        'stdout': "$> %s\n%s" % (cmd, pipe.stdout.read()),
        'stderr': pipe.stderr.read(),
        'returnCode': pipe.returncode
    }
    
    return result

#-----------------------------------
#
#-----------------------------------
def doCmds(cmdList):
    #Note: since the length of info has to be greater than 1 in order to run
    #specific commands the info variable always has to have an extra empty
    #item, remove this item
    cmdList=cmdList[:-1]

    #--------------------------------------
    #verify that the commands should be run
    #--------------------------------------
    msg="Running a list of commands could be potentially harmful to your system"
    msg+=".  Please verify that the following commands should be run:"
    
    print fill(msg, 80)
    
    #<--- implement an "always" option that stores the accepted commands in
    #<--- an sqlite db
    
    for cmd in cmdList:
        print cmd
    
    choice=raw_input("Accept these commands (yes/no)\t")
    
    if choice in ['yes','y']:
        results=[]
        
        for command in cmdList:
            results.append(run(command))
            
        return results
    else:
        return False

#-----------------------------------
#
#-----------------------------------
def findCmd(fileList, path, verbose, action):
    
    setupPyFound=False

    #------------------
    #find a file to run
    #------------------
    for name in fileList:
        if verbose: print "Looking for '%s' in source code..." % name,
        
        (found, loc)=fileSearch(path, name)
        
        if name == 'setup.py' and found: 
            setupPyFound=True
            break
        elif found: break
        else: print ""

    #-----------------------------------------
    #return an empty list if no file was found
    #-----------------------------------------
    if not found: return (None, None)
    
    print "found."

    #------------------------------------------
    #a file was found, change to it's directory
    #------------------------------------------
    os.chdir(loc)
    
    #<--- implement finding the python binary so that user doesn't have to have paths setup
    
    if name == "setup.py": command='python %s build' % name
    elif ".py" in name: command='python %s' % name
    elif "makefile" in name: command='make'
    else: command=name
    
    return (command, setupPyFound)

#--------------------------------
#function that builds the project
#--------------------------------
def build(info, path, verbose):
    if isinstance(info, ListType): return doCmds(info)
    elif '?' in info: (command,setupPyFound)=findCmd(buildFileList, path, verbose, 'build')
    else: (command,setupPyFound)=findCmd([info], path, verbose, 'build')
    
    if command is None: return []
    
    if verbose: print "Building..."
    
    results=run(command)
    results['setup.py']=setupPyFound
    
    return [results]
    
#--------------------------------
#function that tests the project
#--------------------------------
def test(info, path, verbose, setupPy):
    if setupPy:
        command='python setup.py test'
    else:
        if isinstance(info, ListType): return doCmds(info)
        else: (command,_)=findCmd([info], path, verbose)
    
    if verbose: print "Testing..."

    return [run(command)]

def fileSearch(path, name):
    for list in os.walk(path):
        if name in list[2]:
            return (True, list[0])
    
    return (False, "")

#function that checks the reply from the server for problems
def checkReply(reply):
    #check to see if server responded at all
    if reply==[]:
        print "There was a problem communicating with the server"
        print "(are you sure it's running?)"
        sys.exit()
        
    #check to see if retrieval method/location is set
    if 'method' not in reply['result']:
        print "Server did not return method/location for obtaining source code."
        print "(the server is running, but there may be a problem with the build setup)"
        sys.exit()
        
    #check to see if build information is set
    if 'buildInfo' not in reply['result']:
        print "Server did not return build information"
        print "(the server is running, but there may be a problem with the build setup)"
        sys.exit()

    #check to see if build information is set
    if 'testInfo' not in reply['result']:
        print "Server did not return test information"
        print "(the server is running, but there may be a problem with the build setup)"
        sys.exit()

#function that generates a new directory for the build
def newSandbox():
    basePath=os.path.abspath('../sandboxes/')

    if not os.path.exists(basePath): os.mkdir(basePath)

    path=os.path.join(basePath, time.strftime('%m-%d-%Y.%H-%M-%S'))
    fullPath=os.path.abspath(path)
    
    os.mkdir(fullPath)
    
    return fullPath

#function that does the network part of the RPC call
def communicate(server, port, data):
    try:
        conn=httplib.HTTP(server, port)
        conn.putrequest("POST","/")
        conn.putheader("Content-Type","application/json-rpc")
        conn.putheader("Content-Length",str(len(data)))
        conn.endheaders()
        conn.send(data)
        
        errcode, errmsg, headers = conn.getreply()
        fp=conn.getfile()
        
        response=fp.read()
        fp.close()
        
        return json.decode(response)
    except:
        return []

def generateKey():
    hostname=socket.gethostname()
    dir=os.getcwd()
    timestamp=str(time.time())

    return hashlib.sha256(timestamp+hostname+dir).hexdigest()
